// Copyright (c) 2024 CHANGLEI. All rights reserved.

import 'package:charts_grasp/src/chart/utils/enum.dart';
import 'package:charts_grasp/src/circular_chart/renderer/circular_series.dart';
import 'package:charts_grasp/src/circular_chart/renderer/renderer_extension.dart';
import 'package:charts_grasp/src/circular_chart/utils/enum.dart';
import 'package:charts_grasp/src/common/utils/typedef.dart';
import 'package:flutter/material.dart';

class ChartPoint<D> {
  ChartPoint([
    this.x,
    this.y,
    this.radius,
    this.pointColor,
    this.sortValue,
  ]);

  dynamic x;

  num? y;

  num? degree;

  num? startAngle;

  num? endAngle;

  num? midAngle;

  Offset? center;

  String? text;

  late Color fill;

  late Color color;

  late Color strokeColor;

  D? sortValue;

  late num strokeWidth;

  num? innerRadius;

  num? outerRadius;

  bool? isExplode;

  bool? isShadow;

  bool isEmpty = false;

  bool isVisible = true;

  bool isSelected = false;

  late Position dataLabelPosition;

  ChartDataLabelPosition? renderPosition;

  late Rect labelRect;

  Size dataLabelSize = Size.zero;

  bool saturationRegionOutside = false;

  late num yRatio;

  late num heightRatio;

  String? radius;

  Color? pointColor;

  String? trimmedText;

  String? overflowTrimmedText;

  bool isTooltipRenderEvent = false;

  bool labelRenderEvent = false;

  late int index;

  dynamic _data;

  ChartShaderMapper<dynamic>? _pointShaderMapper;

  num? _isLabelUpdated;

  num? _newAngle;

  Shader? get shader => _pointShaderMapper != null && center != null && outerRadius != null
      ? _pointShaderMapper!(
          _data,
          index,
          fill,
          Rect.fromCircle(
            center: center!,
            radius: outerRadius!.toDouble(),
          ),
        )
      : null;

  Rect? _pathRect;
}

class PointHelper {
  const PointHelper._();

  static Rect? getPathRect(ChartPoint<dynamic> point) => point._pathRect;

  static num? getLabelUpdated(ChartPoint<dynamic> point) => point._isLabelUpdated;

  static void setPathRect(ChartPoint<dynamic> point, Rect? pathRect) {
    point._pathRect = pathRect;
  }

  static void setLabelUpdated(ChartPoint<dynamic> point, num? isLabelUpdated) {
    point._isLabelUpdated = isLabelUpdated;
  }

  static ChartShaderMapper<dynamic>? getPointShaderMapper(ChartPoint<dynamic> point) => point._pointShaderMapper;

  static num? getNewAngle(ChartPoint<dynamic> point) => point._newAngle;

  static void setNewAngle(ChartPoint<dynamic> point, num? newAngle) {
    point._newAngle = newAngle;
  }
}

ChartPoint<dynamic> getCircularPoint(CircularSeriesRendererExtension seriesRenderer, int pointIndex) {
  final CircularSeries<dynamic, dynamic> series = seriesRenderer.series;
  late ChartPoint<dynamic> currentPoint;
  final ChartIndexedValueMapper<dynamic>? xMap = series.xValueMapper;
  final ChartIndexedValueMapper<dynamic>? yMap = series.yValueMapper;
  final ChartIndexedValueMapper<dynamic>? sortFieldMap = series.sortFieldValueMapper;
  final ChartIndexedValueMapper<String>? radiusMap = series.pointRadiusMapper;
  final ChartIndexedValueMapper<Color>? colorMap = series.pointColorMapper;
  final ChartShaderMapper<dynamic>? shadeMap = series.pointShaderMapper;

  dynamic xVal;
  num? yVal;
  String? radiusVal;
  Color? colorVal;
  String? sortVal;
  if (xMap != null) {
    xVal = xMap(pointIndex);
  }

  if (xVal != null) {
    if (yMap != null) {
      yVal = yMap(pointIndex);
    }

    if (radiusMap != null) {
      radiusVal = radiusMap(pointIndex);
    }

    if (colorMap != null) {
      colorVal = colorMap(pointIndex);
    }
    if (sortFieldMap != null) {
      sortVal = sortFieldMap(pointIndex);
    }

    currentPoint = ChartPoint<dynamic>(xVal, yVal, radiusVal, colorVal, sortVal);
  }
  currentPoint.index = pointIndex;
  if (shadeMap != null) {
    currentPoint._pointShaderMapper = shadeMap;
  } else {
    currentPoint._pointShaderMapper = null;
  }
  currentPoint.center = seriesRenderer.center;

  return currentPoint;
}
